<?php
/*
 * 搜索元素
 * @Author: LDY dong2406@126.com
 * @Date: 2022-08-23 13:46:19
 * @LastEditors: 搬铁的码农 dong2406@126.com
 * @LastEditTime: 2025-05-12 15:47:29
 */
namespace Ldy\Traits\Model;

trait Trees{

    //通用菜单ID
    protected $publicMenuIds = [];
    //前端按钮权限
    protected $btnPermission = [];

    protected $buildBtnPermission = false;

    protected $cascaderOptionWhere = [];
    /**
     * 构建按钮权限
     *
     * @return $this
     */
    public function buildBtnPermission(){
        $this->buildBtnPermission = true;
        return $this;
    }
    /**
     * 获取按钮权限数组
     *
     * @return Array
     */
    public function getButtonPerimssion(){

        return $this->btnPermission;
    }

    public function getPublicMenuIds(){
        return $this->publicMenuIds;
    }


    public function getTreesNodeString(Int $id){

    }

    
    /**
     * 找到指定id 的所有子级节点
     *
     * @param Int $id 表id
     * @param boolean $status    是否输出全部数据，默认输出全部数据,请检查确认表是否有status字段
     * @param boolean $out_tree 是否输出树的形式，false=>输出二维数组
     * @param boolean $out_self 是否输出自己，false=>只输出子级
     * @return void
     */
    public function getTreesNode(Int $id, $status=false, bool $out_tree=false, bool $out_self=false){
        $model = $this->whereLike('path',"%|$id|%");
        if($status) $model->where('status', 1);
        if($out_self) $model->whereOr("id", $id);

        $data = $model->order('parent_id', 'asc')->select()->toArray();
        
        if(!$out_tree) return $data;

        $res = $this->children($data, $id);

        $res = array_merge($res, $data);
		
		$res = $this->array_sort($res,'rand');

        return $res;
    }
   
    /**
     * 数据树
     *
     * @param array $map 字段映射 ["组装key"=>"数据表字段"]
     * @param array $queryFields 查询字段在grid类中
     * @return void
     */
    public function trees(Array $map = [], $queryFields = []){
        $data = $this->setTreesData($queryFields);

        $id = isset($data[0]) ? $data[0]['parent_id']:0;
		$res = $this->children($data, $id, $map);

        if(!empty($data)) $res = array_merge($res, $data);
		
		$res = $this->array_sort($res,'rand');

		return $res;
	}

    /**
	 * 数据树
	 * 数据表必须要有 parent_id、rand 字段
     *
	 * @return Array
	 */
	public function cascaderOption(String $ValField='id', String $labelField='name', String $randField = 'rand'){
		$model = $this;
        if(!empty($this->cascaderOptionWhere)){
            foreach($this->cascaderOptionWhere as $key=>$v) $model = $model->where($key, $v);
        }
        $data = $model->order('parent_id', 'asc')->select()->toArray();

        $id = isset($data[0]) ? $data[0]['parent_id']:0;
		$res = $this->children($data, $id, ["value" => $ValField, "label"=>$labelField, 'rand'=>$randField]);
		
        if(!empty($data)) $res = array_merge($res, $data);

		$res = $this->array_sort($res,'rand');
		
		return $res;
	}

    public function cascaderOptionWhere($where = []){
        $this->cascaderOptionWhere = $where;
        return $this;
    }

    /**
     * 设置树数据, 有特殊需求的话重写该方法
     *
     * @return Array
     */
    protected function setTreesData($queryFields){
        $param = request()->get();
        $model = $this;
        foreach($queryFields as $item){
            $field = $item['field'];
            $val = isset($param[$field]) ? $param[$field]:null;
            if($val !== null && $val!='ALL') $model = $model->where($field, $val);
        }
        
        $model = $this->treesDataWhere($model);

        $data = $model->order('parent_id', 'asc')->select()->toArray();

        return $data;
    }

    /**
     * 设置输出树数据的条件
     *
     * @param Model $model
     * @return Model
     */
    protected function treesDataWhere($model){
        return $model;
    }


    /**
	 * 数据树
	 * 数据表必须要有 parent_id、rand 字段
	 * @param Array $data
	 * @param [type] $id
	 * @param Array $fields ["组装key"=>"数据表字段"]
	 * @return void
	 */
	protected function children(Array &$data, $id, $fields=[], $level=0){

		$res = [];

        //获取前端按钮菜单
        if($this->buildBtnPermission){
            $this->btnPermission = [];

            foreach($data as $item){
                if(empty($item['meta']) || ($item['meta'] && $item['meta']->type != 'button')) continue;
                $this->btnPermission[] = $item['name'];
            }
            $this->buildBtnPermission = false;
        }
        
		foreach($data as $k => $item){
            
            if(isset($item['is_public']) && $item['is_public'] && !in_array($item['id'],$this->publicMenuIds)) $this->publicMenuIds[] = $item['id'];

			if($item['parent_id'] != $id) continue;
			$iid = $item['id'];
			$tmp = [];
            $item['level'] = $level;

			if(empty($fields)){
				$tmp = $item;
			}else{
				foreach($fields as $key=>$field) {
                    if(strpos($field,'.') !== false){
                        [$k1, $k2] = explode('.', $field);
                        $tmp[$key] = $item[$k1]->$k2;
                    }else{
                        $tmp[$key] = $item[$field];
                    }
                }
				// $tmp = ["value"=>$iid, "label"=>$item['name']];
			}
			
			unset($data[$k]);
			$son = $this->children($data, $iid, $fields, $level+1);

			if(!empty($son)) $tmp['children'] = $this->array_sort($son,'rand');

			$res[] = $tmp;
		}

		return $res;
	}

}